#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_time;
unsigned char IR_state, IR_data[4], IR_pData, IR_dataFlag, IR_repeatFlag, IR_address, IR_command;

/**
  * @brief  红外遥控初始化
  * @param  无
  * @retval 无
  */
void IR_init(void)
{
    Timer0_Init();
    Int0_init();
}

/**
  * @brief  红外遥控获取收到数据帧标志位
  * @param  无
  * @retval 是否收到数据帧，1为收到，0为未收到
  */
unsigned char IR_get_dataflag(void)
{
    if (IR_dataFlag)
    {
        IR_dataFlag = 0;
        return 1;
    }
    
    return 0;
}

/**
  * @brief  红外遥控获取收到连发帧标志位
  * @param  无
  * @retval 是否收到连发帧，1为收到，0为未收到
  */
unsigned char IR_get_repeatflag(void)
{
    if (IR_repeatFlag)
    {
        IR_repeatFlag = 0;
        return 1;
    }
    
    return 0;
}

/**
  * @brief  红外遥控获取收到的地址数据
  * @param  无
  * @retval 收到的地址数据
  */
unsigned char IR_get_address(void)
{
    return IR_address;
}

/**
  * @brief  红外遥控获取收到的命令数据
  * @param  无
  * @retval 收到的命令数据
  */
unsigned char IR_get_command(void)
{
    return IR_command;
}

/* 外部中断0中断函数，下降沿触发执行 */
void Int0_Routine(void) interrupt 0
{
    switch (IR_state)
    {
        case 0:  // 空闲状态
        {
//            P2 = 0;
            Timer0_set_counter(0);  // 定时器清零
            Timer0_run(1);  // 定时器启动
            IR_state = 1;  // 状态转移为1
            break;
        }  
        case 1:  // 第二个下降沿，定时器已经启动，读取counter时间
        {
//            P2 = 0;
            IR_time = Timer0_get_counter();
            Timer0_set_counter(0);
            // 比较start or repeat
            // start: 9 + 4.5 = 13.5 ms * 0.9216
            if (IR_time > 12442 - 500 && IR_time < 12442 + 500)
            {
//                P2 = 0;
                IR_state = 2;
            }
            // repeat: 9 + 2.25 = 11.25 ms
            // 判定值在12MHz晶振下为11250，在11.0592MHz晶振下为10368
            else if (IR_time > 10368 - 500 && IR_time < 10368 + 500)
            {
                IR_repeatFlag = 1;
                Timer0_run(0);  // 计时器停止（也可以不停）
                IR_state = 0;
            }
            // 解码错误：转到本状态：继续搜寻起始信号
            else
            {
                IR_state = 1;
            }
            break;
        }
        case 2:  // 解码
        {
            IR_time = Timer0_get_counter();  // 读取上个中断到这个中断的时间
            Timer0_set_counter(0);  // 清零，为下次中断开始计时
            // 写入数据0: 560 + 560 = 1120 μs * 0.9216
            if (IR_time > 1032 - 500 && IR_time < 1032 + 500)
            {
                // 存入一个字节，4次依次存32位
                // 索引为整数部分，移位为余数部分，当pData为8的倍数时，data索引跳到下一个字节，移位清零重新开始
                IR_data[IR_pData / 8] &= ~(0x01 << (IR_pData % 8));  // 清零&=
                IR_pData++;
            }
            // 写入数据1: 560 + 1690 = 2250 μs * 0.9216
            else if (IR_time > 2074 - 500 && IR_time < 2074 + 500)
            {
                IR_data[IR_pData / 8] |= (0x01 << (IR_pData % 8));  // 置1|=
                IR_pData++;
            }
            // 错误
            else
            {
                IR_pData = 0;
                IR_state = 1;  // 本次数据作废，开始搜寻下个信号
            }
            
            // 数据收集结束
            if (IR_pData >= 32)
            {
                IR_pData = 0;
                // 验证数据正确
                if ((IR_data[0] == ~IR_data[1]) && (IR_data[2] == ~IR_data[3]))
                {
                    IR_address = IR_data[0];  // 转存数据地址
                    IR_command = IR_data[2];  // 转存数据命令
                    IR_dataFlag = 1;  // 数据接收成功标志
                }
                Timer0_run(0);
                IR_state = 0;
            }
            break;
        }
    }
}